/*
 * 描述： <描述>
 * 修改人： rain
 * 修改时间： 2016年01月20日
 * 项目： rainhy-cores-core
 */
package com.rainhy.core.util;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.TypeUtils;

import com.rainhy.core.exception.RainhyIllegalArgException;

/**
 * 校验工具<br>
 * 
 * @author rain
 * @version [版本号, 2015年12月14日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public abstract class CheckUtils {
    /**
     * 
     * 校验银行卡卡号
     *
     * @param cardId 银行卡号
     * 
     * @return boolean [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月2日]
     * @author rain
     */
    public static boolean checkBankCard(String cardId) {
        char bit = getBankCardCheckCode(cardId.substring(0, cardId.length() - 1));
        return cardId.charAt(cardId.length() - 1) == bit;
    }
    
    /**
     * 
     * 完整的判断中文汉字和符号<br>
     * 根据Unicode编码完美的判断中文汉字和符号
     *
     * @param str 被判断的字符串
     * 
     * @return boolean [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月20日]
     * @author rain
     */
    public static boolean isChinese(String str) {
        char[] ch = str.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (isChinese(c)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 
     * 判断对象是否为空
     *
     * @param object 判断对象
     * 
     * @return boolean 是否为空
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static boolean isEmpty(Object object) {
        if (object == null) {
            return true;
        }
        
        if ((object instanceof CharSequence && StringUtils.isBlank((CharSequence) object))
                || (object instanceof Collection<?> && CollectionUtils.isEmpty((Collection<?>) object))
                || (object instanceof Map<?, ?> && MapUtils.isEmpty((Map<?, ?>) object))
                || (object instanceof Iterator && ((Iterator<?>) object).hasNext() == false)
                || (object instanceof Enumeration && ((Enumeration<?>) object).hasMoreElements() == false)
                || (TypeUtils.isArrayType(object.getClass()) && ArrayUtils.isEmpty((Object[]) object))) {
            return true;
        }
        return false;
    }
    
    /**
     * 
     * 判断对象是否非空
     *
     * @param object 判断对象
     * 
     * @return boolean 是否非空
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static boolean isNotEmpty(Object object) {
        return !isEmpty(object);
    }
    
    /** 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位 */
    private static char getBankCardCheckCode(String nonCheckCodeCardId) {
        if (StringUtils.isBlank(nonCheckCodeCardId) || !nonCheckCodeCardId.matches("\\d+")) {
            throw new RainhyIllegalArgException("银行卡号必须是数字!");
        }
        char[] chs = nonCheckCodeCardId.trim().toCharArray();
        int luhmSum = 0;
        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
    }
    
    // 根据Unicode编码完美的判断中文汉字和符号
    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }
}
